#coding: utf8
'''
==================================================================================
Created on 2020-10-26
Author: Simon
==================================================================================
'''
from datetime import datetime
from src.libs.database import Database
from src.common.base import Task, today, workday as WD


def search_task(key, p_id): 
    db = Database()
    sql = "select id, moduleId from task where projectId=%s and name like '%{}%'".format(key)
    dt = db.read_all(sql, [p_id])
    return dt

def get_user_list(org_id):
    db = Database()
    sql = "select username, realName, nickname, type, level, orgId, orgName, orgLabel, \
        status from user where orgId=%s"
    info = db.read_all(sql, (org_id, ))
    return info

def get_user_info(username):
    db = Database()
    sql = "select nickname, realName, type, level, orgId, orgName, orgLabel, \
        status from user where username=%s"
    info = db.selectOne(sql, (username, ))
    return info


def create_task(project_id, module_id, create_user, name, is_multi, plan_end_time, 
                description="", depart=None, executor=None):
    m = Task(project_id, module_id, None)
    if not depart:
        info = get_user_info(create_user)
        if info: depart = info['orgId']
    if not executor: executor = create_user
    m.set_data(is_multi, name, create_user, description, plan_end_time, executor, depart)
    flag, msg = m.create()
    return (flag if flag > -1 else False), msg

'''TODO：兼容凌晨提交日志情况'''
def is_today(tm):
    return tm.strftime('%Y-%m-%d') == datetime.now().strftime('%Y-%m-%d')
def fid(id_): return -1 if id_ == None else id_


'''
进度控制：本日进度不能小于历史进度，但可修改计划
进度说明：
        一、非协作任务：
            1.若有最新变更记录（变更后个人未提交过日志），则以记录中进度值为最小值；
            2.若无最新变更记录，则以个人历史最后记录为最小值，无记录则为0；
        二、协作任务：
            1）若有最新变更记录（变更后协作的人均未提交过日志），则以记录中进度值为最小值；
            2）若无最新变更记录：
            1.若当日有人提交过记录，则以此值为最终值，不可编辑；
            2.若当日无人提交过记录，则以个人历史最后记录为最小值，无记录则为0；
    二次修改：
        是否协作任务的逻辑可以统一，以任务为导向，不管人
注：适用于新提交日志，不考虑多端并发，应在提交接口处限制今日未提交情况：新增与修改严格限定。
'''        
def get_task_control(t_id, user=None, db=None):
    if not db: db = Database()
    '''取任务下所有人的最后提交记录'''
    sqlR = '''select r.user, updateTime, progress from record_day r right join (
        select max(updateTime) tm from record_day where taskId=%s
    ) a on r.updateTime=a.tm where taskId=%s order by progress desc limit 1
    '''
    rec = db.selectLine(sqlR, (t_id, t_id))
    pla = get_task_last_change(t_id, db)
    if not pla: pla = [None, None, None]
    
    return analysis_task_status(user, rec, pla[1], pla[2])

'''取任务下的最新变更记录'''
def get_task_last_change(t_id, db):
    sqlP = '''select a.executor, updateTime, progress, multiUser from plan_change a right join 
          (select max(updateTime) tm from plan_change b where taskId=%s) b
        on a.updateTime=b.tm where taskId=%s order by progress limit 1  
    '''
    return db.selectLine(sqlP, (t_id, t_id))
    
    
'''
任务进度控制
    param:
        record - [user, updateTime, progress]
逻辑说明：
    1.无计划变更则以最后提交为准，无则为0
    2.有计划变更则以最新时间对应的进度为准
    注：提交时需检查进度合法性
    progress - 是否协作任务且今日已由其他人设置。
    注：若有最新计划变更，则协作任务不受其他成员今日进度限制
'''
def analysis_task_status(user, record, plan_time=None, plan_progress=None):    
    pla = [plan_time, plan_progress] if plan_time else None
    info = {'min': 0, 'progress': None}
    if record:
        ru, rt, rp = record
        info['min'] = rp
        '''今日他人已设置'''
        if user != ru and is_today(rt): info['progress'] = rp
        '''有计划则看时间'''
        if pla and pla[0] > rt: info['min'], info['progress'] = pla[1], None  
    else:
        '''无提交但有计划变更，则以计划为准'''
        if pla: info['min'] = pla[1] 
    '''End If'''
    
    return info


'''获取一批任务的限制状态'''
def get_task_ctls(user, tids, db=None):
    if not db: db = None

    sql = '''select tid, user, tm, progress from 
        (select taskId tid, max(updateTime) tm from record_day where 
        taskId in ({}) and (user!=%s or (user=%s and workday!=%s)) group by taskId
        ) a left join record_day r 
        on tid=r.taskId and tm=r.updateTime'''.format(','.join('%s' for t in tids))
    res = db.read_all(sql, tids + [user, user, WD()])
    rcds = {d['tid']: [d['user'], d['tm'], d['progress']] for d in res}

    sql = '''select tid, tm, p.progress progress from 
        (select taskId tid, max(updateTime) tm from plan_change b where 
        taskId in ({}) group by taskId) a left join plan_change p 
        on tid=p.taskId and tm=p.updateTime'''.format(','.join('%s' for t in tids))
    res = db.read_all(sql, tids)
    plas = {d['tid'] : [d['tm'], d['progress']] for d in res}
    
    infos = {}
    for t in tids:
        t = int(t) 
        pt, pp = None, None
        if t in plas: pt, pp = plas[t]
        infos[t] = analysis_task_status(user, rcds.get(t, None), pt, pp)
    
    return infos


'''则从日志提交记录取数据'''
def get_task_hint(user, pid=None, project=None):
    if project == "": project = None
    if not pid and not project: return []
    db = Database()
    params = [user]
    sql = '''select task, taskId, moduleId from record_day r left join user u 
        on u.username=r.user where u.orgId=(select orgId from user where username=%s) 
        and task is not null'''
    if pid == None or int(pid) == -1:
        sql += " and project=%s"
        params.append(project)
    else:
        sql += " and projectId=%s"
        params.append(pid)
    sql = "select task, taskId, moduleId from ({}) a group by task, taskId, moduleId".format(sql) 
    ts = {}
    for task, taskId, moduleId in db.selectEx(sql, params):
        if task not in ts: 
            ts[task] = [taskId, moduleId]
        else:
            if ts[task][0] == None: ts[task] = [taskId, moduleId]  
    '''End For'''
    data = [{'name': k, 'id': fid(v[0]), 'mid': fid(v[1]) } for k, v in ts.items()]
    
    return data
    
   
def get_task_list(mid, executor, category, department, hide_done=False):
    db = Database()
    keys = ['name', 'moduleId', 'createUser', 'executor', 'description', 'category', 
            'department', 'planEndTime', 'multiUser', 'multiOrg']
    sql, params = "select t.id, " + ','.join(keys) + ", t.createTime, t.mark,\
        t.status tStatus, t.progress p, pTime, utm, \
        IFNULL(uc, 0) userCount, IFNULL(b.progress, 0) progress, orgLabel \
        from task t left join user u on executor=u.username \
        left join \
        (select taskId, count(*) uc from \
            (select taskId, user from record_day where moduleId=%s group by taskId, user \
            ) a group by taskId \
        ) r on t.id=r.taskId \
        left join \
        ( select taskId, updateTime utm, progress, workday from record_day r where \
            updateTime=(select max(updateTime) from record_day d \
                where r.taskId=d.taskId and r.moduleId=%s) \
        ) b on t.id=b.taskId where t.moduleId=%s", [mid, mid, mid]
    
    if executor != '': 
        sql += " and executor=%s"
        params.append(executor)
    if category != '': 
        sql += " and category=%s"
        params.append(category)
    if department != '': 
        sql += " and department=%s" # ( or multiOrg=1)
    if hide_done:
        '''去掉已完成的任务，但要兼顾今天的刚完成协作任务'''
        sql += " and t.status=0 and (b.progress<100 or b.progress is null or \
                (b.progress=100 and b.workday=%s))"
        params.append(today())
    sql += " order by b.progress, utm desc"
    data = db.read_all(sql, params)
    
    for line in data: 
        if check_progress(line): line['progress'] = line['p']
        if line['planEndTime']: line['planEndTime'] = str(line['planEndTime'])
        if line['createTime']: line['createTime'] = str(line['createTime'])
        if line['pTime']: line['pTime'] = str(line['pTime'])
        if line['utm']: line['utm'] = str(line['utm'])
    return data

def check_progress(line):
    if not line['utm'] or not line['pTime']: return None
    if line['utm'] < line['pTime']: return line['p']
    return None
    

'''冲突'''
def add_change(user, t_id, plan_time, progress, reason):
    db = Database()
    '''获取任务基本信息'''
    sql = "select planEndTime, multiUser from task where id=%s"
    cnx, cursor = db.Query(sql, (t_id, ))
    src_time, multi_user = cursor.fetchone()
    
    '''获取历史变更信息'''
    sql = "select id, executor, createTime from plan_change where taskId=%s order by createTime desc limit 1 for update"
    cursor = db.select(sql, (t_id, ))
    line = cursor.fetchone()
    flag = True  
    
    if line:
        _, executor, tm = line
        '''协同任务或该用户已提交计划未执行'''
        if multi_user or executor == user: 
            sql = "select count(*) from record_day where taskId=%s and workday>%s "
            db.select(sql, (t_id, tm), cursor)
            count = cursor.fetchone()[0]
            if count == 0: flag = False
        '''End If 2'''
    '''End If 1'''
             
    '''有已更改的计划暂未实施，不能新增'''
    if not flag: 
        cursor.close()
        return False, "该任务有已更改的计划暂未实施，不能新增''"
    
    sql = "insert into plan_change (taskId, srcTime, planTime, changeUser, executor, progress, reason, multiUser) \
        values (%s, %s, %s, %s, %s, %s, %s, %s)"
    params = (t_id, src_time, plan_time, user, user, progress, reason, multi_user)
    flag, _ = db.Transaction([[sql, params]], cnx, cursor)
    
    return flag, "操作失败"
    
    

    
if __name__ == '__main__':
#     create_task(1, 1, 'david', '任务1', True, "2020-11-12", "HelloKetty")
    # print(get_task_list(38, "", "", "", "liuhong"))
    # get_user_info("liuhong")
    
#     get_task_record(1, "admin")
#     print(add_change("admin", 1, "2020-10-31", 32, "啊大大"))
#     print(get_task_record(1, 1, ""))
    # get_task_control(2)
    
    pass
